package controller

import (
	"image-server/config"
	models "image-server/dao"
	"image-server/middleware"
	response "image-server/models"
	"image-server/models/dto"
	service "image-server/services"
	"io"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// ImageController 图片控制器，处理与图片相关的HTTP请求
type ImageController struct {
	imageService *service.ImageService // 图片服务层实例，处理图片相关业务逻辑
}

// NewImageController 创建图片控制器实例
// 返回：初始化后的ImageController指针
func NewImageController() *ImageController {
	return &ImageController{
		imageService: &service.ImageService{},
	}
}

// UploadImage 处理图片上传（包含缩略图生成逻辑）
// 请求方式：POST
// 功能：验证用户身份后，接收图片文件并调用服务层完成上传
func (c *ImageController) UploadImage(ctx *gin.Context) {
	// 从中间件获取用户信息
	user, err := middleware.GetUser(ctx)
	if err != nil || user == nil {
		response.Error(ctx.Writer, http.StatusUnauthorized, "未授权访问: "+err.Error())
		return
	}

	// 解析表单中的相册ID
	albumID, err := strconv.ParseInt(ctx.PostForm("album_id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "相册ID格式错误")
		return
	}

	// 获取上传的图片文件
	file, err := ctx.FormFile("image")
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "获取图片文件失败: "+err.Error())
		return
	}

	// 打开文件获取内容
	fileContent, err := file.Open()
	if err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "读取文件内容失败: "+err.Error())
		return
	}
	defer fileContent.Close()

	// 读取文件字节流
	content, err := io.ReadAll(fileContent)
	if err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "文件内容读取失败: "+err.Error())
		return
	}

	// 调用服务层UploadImage方法完成上传
	image, err := c.imageService.UploadImage(
		user.ID,
		user.WpsUID,
		albumID,
		file.Filename,
		file.Size,
		content,
		ctx.PostForm("title"),       // 图片标题
		ctx.PostForm("description"), // 图片描述
		ctx.PostForm("tags"),        // 图片标签
	)
	if err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "图片上传失败: "+err.Error())
		return
	}

	// 返回成功响应
	response.Success(ctx.Writer, image, "图片上传成功")
}

// GetAlbumImages 获取相册内图片列表
// 请求方式：GET
// 功能：根据相册ID获取图片列表，支持分页，验证访问权限
func (c *ImageController) GetAlbumImages(ctx *gin.Context) {
	// 从中间件获取用户信息（可能为nil，支持未登录访问公开相册）
	user, _ := middleware.GetUser(ctx)

	// 解析路径参数中的相册ID
	albumID, err := strconv.ParseInt(ctx.Param("albumId"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "无效的相册ID")
		return
	}

	// 解析分页参数，默认第1页，每页10条，限制最大每页50条
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
	if page <= 0 {
		page = 1
	}
	if limit <= 0 || limit > 50 {
		limit = 10
	}

	// 调用服务层获取相册内图片列表（传入用户ID用于权限校验）
	images, total, err := c.imageService.GetImagesByAlbum(albumID, user.ID, page, limit)
	if err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "获取图片列表失败: "+err.Error())
		return
	}

	// 构建包含分页信息的响应数据
	data := gin.H{
		"images": images,
		"pagination": gin.H{
			"total": total,
			"page":  page,
			"limit": limit,
		},
	}
	response.Success(ctx.Writer, data)
}

// DeleteImage 删除图片
// 请求方式：DELETE
// 功能：验证用户身份（必须为图片所有者）后，根据图片ID删除图片
func (c *ImageController) DeleteImage(ctx *gin.Context) {
	// 从中间件获取用户信息
	user, err := middleware.GetUser(ctx)
	if err != nil || user == nil {
		response.Error(ctx.Writer, http.StatusUnauthorized, "未授权访问: "+err.Error())
		return
	}

	// 解析路径参数中的图片ID
	imageID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "无效的图片ID")
		return
	}

	// 调用服务层删除图片（使用用户ID验证所有权）
	if err := c.imageService.DeleteImage(imageID, user.ID); err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "删除图片失败: "+err.Error())
		return
	}

	// 返回删除成功响应
	response.Success(ctx.Writer, nil, "图片删除成功")
}

// GetImageDetail 获取图片详情（标题、描述、OSS路径等）
// 请求方式：GET
// 功能：根据图片ID获取详情，验证访问权限
func (c *ImageController) GetImageDetail(ctx *gin.Context) {
	// 解析路径参数中的图片ID
	imageID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "图片ID格式错误")
		return
	}

	// 从中间件获取当前用户信息（用于权限校验）
	user, _ := middleware.GetUser(ctx)
	var userID int64
	if user != nil {
		userID = user.ID
	}

	// 调用服务层获取图片详情（验证所有权）
	image, err := c.imageService.GetImageDetail(imageID, userID)
	if err != nil {
		switch err.Error() {
		case "图片不存在":
			response.Error(ctx.Writer, http.StatusNotFound, err.Error())
		case "无权访问该图片":
			response.Error(ctx.Writer, http.StatusForbidden, err.Error())
		default:
			response.Error(ctx.Writer, http.StatusInternalServerError, "获取图片详情失败: "+err.Error())
		}
		return
	}

	// 返回图片详情
	response.Success(ctx.Writer, image, "success")
}

// UpdateImage 更新图片信息（标题、描述、标签）
// 请求方式：PUT
// 功能：验证用户身份（必须为图片所有者）后，更新图片信息
func (c *ImageController) UpdateImage(ctx *gin.Context) {
	// 解析路径参数中的图片ID
	imageID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "图片ID格式错误")
		return
	}

	// 从中间件获取当前用户信息（必须是图片所有者）
	user, err := middleware.GetUser(ctx)
	if err != nil || user == nil {
		response.Error(ctx.Writer, http.StatusUnauthorized, "未授权访问: "+err.Error())
		return
	}

	// 解析请求体参数（使用DTO）
	var req dto.UpdateImageRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "请求参数解析失败: "+err.Error())
		return
	}

	// 调用服务层更新图片信息（使用用户ID验证所有权）
	updatedImage, err := c.imageService.UpdateImage(imageID, user.ID, req.Title, req.Description, req.Tags)
	if err != nil {
		switch err.Error() {
		case "图片不存在":
			response.Error(ctx.Writer, http.StatusNotFound, err.Error())
		case "无权修改该图片":
			response.Error(ctx.Writer, http.StatusForbidden, err.Error())
		default:
			response.Error(ctx.Writer, http.StatusInternalServerError, "更新图片信息失败: "+err.Error())
		}
		return
	}

	// 返回更新后的图片信息
	response.Success(ctx.Writer, updatedImage, "图片信息更新成功")
}

// DownloadImage 生成图片下载链接并以统一格式返回
// 请求方式：GET
// 功能：验证访问权限后，生成临时下载链接并返回
func (c *ImageController) DownloadImage(ctx *gin.Context) {
	// 解析路径参数中的图片ID
	imageID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "图片ID格式错误")
		return
	}

	// 解析有效期
	expiresInStr := ctx.Query("expires_in")
	var expiresIn time.Duration
	if expiresInStr == "" {
		// 从配置读取默认有效期（如1小时）
		expiresIn = time.Duration(config.Aliyun.TIMEEXPIRES) * time.Second
	} else {
		// 解析传入的有效期（单位为秒）
		expiresSec, err := strconv.ParseInt(expiresInStr, 10, 64)
		if err != nil || expiresSec <= 0 {
			response.Error(ctx.Writer, http.StatusBadRequest, "传入的时间有错误")
			return
		}
		expiresIn = time.Duration(expiresSec) * time.Second
	}

	// 从中间件获取当前用户信息（用于权限校验）
	user, _ := middleware.GetUser(ctx)
	var userID int64
	if user != nil {
		userID = user.ID
	}
	// 调用服务层生成临时下载链接
	downloadURL, err := c.imageService.GenerateDownloadURL(imageID, userID, expiresIn, "original")
	if err != nil {
		switch err.Error() {
		case "图片不存在":
			response.Error(ctx.Writer, http.StatusNotFound, err.Error())
		case "无权下载该图片":
			response.Error(ctx.Writer, http.StatusForbidden, err.Error())
		default:
			response.Error(ctx.Writer, http.StatusInternalServerError, "生成下载链接失败: "+err.Error())
		}
		return
	}
	// 3. 调用model层插入分享记录（share_key直接使用downloadURL）
	_, err = models.CreateShareWithKey(imageID, userID, downloadURL, expiresIn)
	if err != nil {
		response.Error(ctx.Writer, http.StatusInternalServerError, "生成分享链接失败: "+err.Error())
		return
	}
	// 以统一格式返回下载链接
	response.Success(ctx.Writer, gin.H{"download_url": downloadURL}, "下载链接生成成功")
}

// DisplayImage 生成图片访问链接并直接重定向（支持原图/缩略图切换）
// 功能：验证访问权限后，根据type参数生成对应图片的临时访问链接并自动重定向
func (c *ImageController) DisplayImage(ctx *gin.Context) {
	// 1. 解析路径参数中的图片ID
	imageID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		response.Error(ctx.Writer, http.StatusBadRequest, "图片ID格式错误")
		return
	}

	// 2. 解析显示类型参数（原图/缩略图）
	displayType := ctx.Query("type")
	if displayType != "original" && displayType != "thumb" {
		displayType = "original" // 默认显示原图
	}

	// 3. 解析有效期参数
	expiresInStr := ctx.Query("expires_in")
	var expiresIn time.Duration
	if expiresInStr == "" {
		// 从配置读取默认有效期
		expiresIn = time.Duration(config.Aliyun.TIMEEXPIRES) * time.Second
	} else {
		expiresSec, err := strconv.ParseInt(expiresInStr, 10, 64)
		if err != nil || expiresSec <= 0 {
			response.Error(ctx.Writer, http.StatusBadRequest, "传入的时间参数错误")
			return
		}
		expiresIn = time.Duration(expiresSec) * time.Second
	}

	// 4. 获取当前用户信息（用于权限校验）
	user, _ := middleware.GetUser(ctx)
	var userID int64
	if user != nil {
		userID = user.ID
	}

	// 5. 根据类型生成对应图片的访问链接
	var displayURL string

	// 生成缩略图访问链接
	displayURL, err = c.imageService.GenerateDownloadURL(imageID, userID, expiresIn, displayType)

	// 6. 错误处理
	if err != nil {
		switch err.Error() {
		case "图片不存在":
			response.Error(ctx.Writer, http.StatusNotFound, err.Error())
		case "无权访问该图片":
			response.Error(ctx.Writer, http.StatusForbidden, err.Error())
		case "缩略图不存在":
			response.Error(ctx.Writer, http.StatusNotFound, err.Error())
		default:
			response.Error(ctx.Writer, http.StatusInternalServerError, "生成访问链接失败: "+err.Error())
		}
		return
	}
	// 7. 重定向到图片URL
	ctx.Redirect(http.StatusFound, displayURL)
}
